home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / TEXTEDIT.SWG / 0014_Full Screen Editor.pas < prev   
Pascal/Delphi Source File  |  1994-05-26  |  41KB  |  1,170 lines

  1.  
  2. Unit MPEditor;  { VERSION 1.0  May 14, 1994 }
  3. {  A general full-screen text editor that should compile under varying
  4.    versions of Borland's Turbo Pascal, relying solely on the CRT
  5.    (and System) units.
  6.  
  7.  (c) 1994, Michael Perry / Progressive Computer Services, Inc.
  8.             All rights reserved worldwide.
  9.  
  10.   LICENSE:  This code is NOT Public Domain; It can be freely
  11.             distributed as long as it is not modified in any
  12.             form.  If you incorporate any part of the code into
  13.             a program, please credit Mike Perry in the program;
  14.             No other remuneration or consideration necessary,
  15.             although it would be nice to get a "thank you" postcard.
  16.             If you have suggestions or enhancements (please do)
  17.             send them to me and I'll make sure that you get
  18.             credit and that this unit will be continually updated.
  19.  
  20.     Author: Mike Perry / Progressive Computer Services, Inc.
  21.             PO Box 7638, Metairie, LA 70010 USA
  22.             BBS: (504) 835-0085  FAX: (504) 834-2160
  23.             Fidonet: 1:396/21  Cserve: 71127,2105  AOL: Arpegi0
  24.             Internet: 71127.2105@compuserve.com    PAN: MIKEPERRY
  25.             Unison: MIKEP
  26.  
  27.   USAGE:    MPEDITOR manipulates text in an allocated area of memory
  28.             specified by the TXT^ pointer.  To incorporate this unit
  29.             into your program, simply copy your text into the array of
  30.             byte specified by TXT^ and call the appropriate procedures.
  31.             Supported commands:
  32.               Arrow keys for cursor movement, INS, DEL, PgUp, PgDn
  33.               CTRL-(left/right) moves cursor to next word;
  34.               ^Y = delete line,
  35.               ^B = reformat text from cursor to end of paragraph
  36.               Ctrl-PgUp = go to top of file
  37.               Ctrl-PgDn = go to end of file
  38.   NOTES:
  39.   % Statements in the unit which are commented out pertain to features
  40.     and options which are either for demonstration purposes or have
  41.     yet to be implemented; look for updates soon.
  42.   % This editor unit assumes that linefeed characters (#10) are
  43.     stripped from the input prior to editing.  If you import
  44.     data to be edited, make sure you convert CR+LF to CR!!
  45.   % The following routines are critical to performance and if
  46.     implemented in ASM would improve efficiency of the unit:
  47.     GET_LINE_DATA, SET_POSITION, SET_CURSOR
  48.     If you can help, contact me at the addresses at the top.
  49. }
  50. {$R-}   { range checking off - causes error when referencing buffer array }
  51.  
  52. { If you want to implement your own screen i/o routines, look for the
  53.   USEQWIK directive which identifies areas in the program where you can
  54.   make modifications to suit your objective }
  55. {-$DEFINE USEQWIK} { implements FAST direct screen writing / requires }
  56.                    { Eagle Performance Software's QWIK screen units }
  57.                    { available as Shareware }
  58. INTERFACE
  59.  
  60. {$IFDEF USEQWIK}
  61.   USES     CRT,Qwik;
  62. {$ELSE}
  63.   USES     CRT;
  64. {$ENDIF}
  65.  
  66. CONST
  67.   TEXTMAX:WORD= 40000; { Maximum size of text editing buffer in bytes }
  68.   CR       = 13;       { ordinal value used to indicate a new line }
  69.   SPACE    = 32;       { ordinal value used to indicate a space }
  70.   REFORMAT = 2;        { ordinal value to initiate reformat command / CTRL-B }
  71.   TABSIZE  = 5;        { tab stop every five characters }
  72.  
  73. TYPE
  74.   TXT_TYPE  = ARRAY [1..1] OF BYTE;
  75.  
  76. VAR
  77.   TXT       : ^TXT_TYPE;    { TEXT BUFFER, pointer to memory block }
  78.  
  79.   { operational status variables ------(set during operation)------------- }
  80.   TEXTSIZE  : LONGINT;      { size of txt array in use / max current index }
  81.   POSITION  : LONGINT;      { index of current (cursor) position in TXT array }
  82.   WINTOP    : LONGINT;      { index position in buffer of top of text window }
  83.   XLINE     : BOOLEAN;      { TRUE if cursor position outside of data area }
  84.   INSERTON  : BOOLEAN;      { TRUE indicates insert mode on }
  85.   VROW,
  86.   VCOLUMN   : BYTE;         { VIRTUAL ROW/COLUMN position within editing area }
  87.   WIDTH,
  88.   HEIGHT    : BYTE;         { width and height of current editing window }
  89.   SCRBUMP   : BYTE;         { chars to bump over display / not to exceed
  90. WIDTH! }
  91.   OFFSET    : LONGINT;      { screen display offset, column position to begin
  92. displaying }
  93. {  MARKSTART,
  94.    MARKEND  : LONGINT;      { start/end index of marked text / NOT IMPLEMENTED
  95. }
  96.   { operational configuration vars ----(set by user)----------------------- }
  97.   MARKATTR,                 { marked text attribute }
  98.   BACKATTR,                 { background text window attribute }
  99.   NORMATTR,                 { attribute values for normal & hilighted text }
  100.   BORDATTR  : WORD;         { attribute value for border }
  101.   R1,C1,                    { row,column of upper left coord of edit window }
  102.   R2,C2     : BYTE;         { row,column of lower right coord on edit win }
  103.   MAXCOLUMN : LONGINT;      { maximum line length/column size, 0=No Limit }
  104. {  MAXROW    : LONGINT;      { maximum number of lines allowed, 0=No Limit }
  105.  
  106.   { prototypes ------------------------------------------------------------ }
  107.  
  108.    {FUNCTION GETINPUT(VAR FUNCTIONKEY:BOOLEAN):BYTE; NEAR }
  109.    {FUNCTION SPACES(COUNT:BYTE):STRING;              NEAR }
  110.    {PROCEDURE CLEAR_TXT;                             NEAR }
  111.   FUNCTION GETTEXTEND:LONGINT;
  112.   FUNCTION INITIALIZE_TXT(VAR PTXT:POINTER;SIZE:LONGINT):BOOLEAN;
  113.   PROCEDURE DISPOSE_TXT(VAR PTXT:POINTER;SIZE:LONGINT);
  114.    {PROCEDURE DRAW_BOX(R1,C1,R2,C2:BYTE);            NEAR }
  115.    {PROCEDURE INITIALIZE_WINDOW(R1,C1,R2,C2:BYTE);   NEAR }
  116.    {PROCEDURE CLEAR_WINDOW;                          NEAR }
  117.    {PROCEDURE CLEAR_LINE;                            NEAR }
  118.    {PROCEDURE BUMP_TXT(COUNT:LONGINT);               NEAR }
  119.    {PROCEDURE DEL_CHARS(COUNT:LONGINT);              NEAR }
  120.    {PROCEDURE GET_LINE_DATA(POS:LONGINT; VAR STARTINDEX,ENDINDEX,COL:LONGINT);}
  121.    {PROCEDURE STUFF_TXT(s:string);                   NEAR }
  122.   FUNCTION WINBOTTOM:LONGINT;
  123.    {PROCEDURE SHOW_LINE;                             NEAR }
  124.   PROCEDURE SHOW_TXT;
  125.   PROCEDURE DISPLAY_TXT(VAR PT:POINTER);
  126.   PROCEDURE SCROLLUP(LINES:BYTE);
  127.   PROCEDURE SCROLLDOWN(LINES:BYTE);
  128.    {PROCEDURE SET_POSITION;                          NEAR }
  129.    {PROCEDURE SET_CURSOR;                            NEAR }
  130.    {PROCEDURE WORD_WRAP(startpoint,endpoint,length:LONGINT);}
  131.    {FUNCTION LINEUP:LONGINT;                         NEAR }
  132.    {FUNCTION LINEDOWN:LONGINT;                       NEAR }
  133.   PROCEDURE READ_TXT(VAR PT:POINTER;FILENAME:STRING;VAR TEXTSIZE:LONGINT);
  134.    {PROCEDURE DIRECTION(C:BYTE);                     NEAR }
  135.    {FUNCTION PARSE_INPUT:BYTE;                       NEAR }
  136.   PROCEDURE SETUP_TEXT_SETTINGS(Row1,Column1,Row2,Column2:BYTE;DRAWBOX:BOOLEAN) ;
  137.   PROCEDURE EDIT(PT:POINTER;VAR RETURNCODE:BYTE);
  138.  
  139. IMPLEMENTATION
  140.  
  141. (***************************************************************************)
  142. FUNCTION GETINPUT(VAR FUNCTIONKEY:BOOLEAN):BYTE;
  143. { read keyboard and return character/function key }
  144. VAR CH: CHAR;
  145. BEGIN
  146.   CH:=ReadKey;
  147.   IF (CH=#0) THEN
  148.     BEGIN
  149.       CH:=ReadKey;
  150.       FUNCTIONKEY:=TRUE;
  151.     END
  152.   ELSE FUNCTIONKEY:=FALSE;
  153.   GETINPUT:=ORD(CH);
  154. END;
  155. (***************************************************************************)
  156. FUNCTION SPACES(COUNT:BYTE):STRING;
  157. { returns COUNT number of spaces }
  158. { NOTE: Unpredictable results if count exceeds 255!! }
  159. var temp:string;
  160. BEGIN
  161.   TEMP:='';
  162.   WHILE COUNT>0 DO BEGIN
  163.     TEMP:=TEMP+#32;
  164.     DEC(COUNT);
  165.   END;
  166.   SPACES:=TEMP;
  167. END;
  168. (***************************************************************************)
  169. PROCEDURE CLEAR_TXT;
  170. { zeros the text array & associated values }
  171. BEGIN
  172.   fillchar(txt^,TEXTMAX,0);
  173.   textsize:=0;
  174.   position:=1;
  175. END;
  176. (***************************************************************************)
  177. FUNCTION GETTEXTEND:LONGINT;
  178. { find the end of text by looking for null character
  179.   %% This is a technique that I use to identify the actual size of
  180.      a text buffer; if you're reading data from a disk structure,
  181.      unless you save the actual size, you'll need to determine it.
  182.      I make sure any unused area in my text buffer is padded with
  183.      nuls }
  184. var I:longint;
  185. BEGIN
  186.   FOR I:=1 TO TEXTMAX DO
  187.     IF TXT^[I]=0 THEN BEGIN
  188.       GETTEXTEND:=I-1;
  189.       EXIT;
  190.     END;
  191.   GETTEXTEND:=TEXTSIZE;
  192. END;
  193. (***************************************************************************)
  194. FUNCTION INITIALIZE_TXT(VAR PTXT:POINTER;SIZE:LONGINT):BOOLEAN;
  195. { create/allocate memory for text buffer }
  196. BEGIN
  197.   if MaxAvail < SIZE then
  198.     INITIALIZE_TXT:=FALSE     { not enough available memory }
  199.   else BEGIN
  200.     GETMEM(PTXT,SIZE);
  201.     INITIALIZE_TXT:=TRUE;
  202.     TEXTMAX:=SIZE;            { set max size of text }
  203.     TXT:=PTXT;                { establish pointer for routines }
  204.     CLEAR_TXT;                { zero text }
  205.   END;
  206. END;
  207.  
  208. (***************************************************************************)
  209. PROCEDURE DISPOSE_TXT(VAR PTXT:POINTER;SIZE:LONGINT);
  210. { disposes text buffer }
  211. BEGIN
  212.   FREEMEM(PTXT,SIZE);
  213. END;
  214. (***************************************************************************)
  215. PROCEDURE DRAW_BOX(R1,C1,R2,C2:BYTE);
  216. { surrounds the specified area with a box }
  217. { NOTE! There are no checks to make sure the box area isn't off the screen!
  218.         and this (and other) routines must be slightly modified if you want
  219.         the text area to fill up the entire screen due to anomolies with
  220.         TP's WINDOW function }
  221. var I:byte;
  222. BEGIN
  223. {$IFDEF USEQWIK}
  224.   { draw horizontal line }
  225.   FOR I:=(C1-1) TO (C2+1) DO BEGIN
  226.     qwrite(R1-1,I,BORDATTR,'─');
  227.     qwrite(R2+1,I,BORDATTR,'─');
  228.   END;
  229.   { draw vertical line }
  230.   FOR I:=(R1-1) TO (R2+1) DO BEGIN
  231.     QWRITE(I,C1-1,BORDATTR,'│');
  232.     QWRITE(I,C2+1,BORDATTR,'│');
  233.   END;
  234.   QWRITE(R1-1,C1-1,BORDATTR,'┌');
  235.   QWRITE(R2+1,C1-1,BORDATTR,'└');
  236.   QWRITE(R1-1,C2+1,BORDATTR,'┐');
  237.   QWRITE(R2+1,C2+1,BORDATTR,'┘');
  238. {$ELSE}
  239.   TEXTATTR:=BORDATTR;
  240.   { draw horizontal line }
  241.   FOR I:=(C1-1) TO (C2+1) DO BEGIN
  242.     GOTOXY(I,R1-1); WRITE('─');
  243.     GOTOXY(I,R2+1); WRITE('─');
  244.   END;
  245.   { draw vertical line }
  246.   FOR I:=(R1-1) TO (R2+1) DO BEGIN
  247.     GOTOXY(C1-1,I); WRITE('│');
  248.     GOTOXY(C2+1,I); WRITE('│');
  249.   END;
  250.   GOTOXY(c1-1,r1-1); WRITE('┌');
  251.   GOTOXY(c1-1,r2+1); WRITE('└');
  252.   GOTOXY(c2+1,r1-1); WRITE('┐');
  253.   GOTOXY(c2+1,r2+1); WRITE('┘');
  254.   TEXTATTR:=NORMATTR;
  255. {$ENDIF}
  256. END;
  257. (***************************************************************************)
  258. PROCEDURE INITIALIZE_WINDOW(R1,C1,R2,C2:BYTE);
  259. { defines text window and clears screen }
  260. BEGIN
  261. {$IFNDEF USEQWIK}
  262.   WINDOW(C1,R1,C2+1,R2);
  263. {$ENDIF}
  264. END;
  265. (***************************************************************************)
  266. PROCEDURE CLEAR_WINDOW;
  267. { clears the current text window }
  268. BEGIN
  269. {$IFDEF USEQWIK}
  270.   QFILL(r1,c1,HEIGHT,WIDTH,BACKATTR,#32);
  271. {$ELSE}
  272.   textattr:=backattr;
  273. { since TP forces an unwanted scroll when writing to the lower right corner
  274.   of a window, we create a window 1-column larger and init a smaller one when
  275.   we want to clear the screen, there is an extra column defined in the
  276.   working window so that unwanted scrolls are not accomplished }
  277.   WINDOW(C1,R1,C2,R2);
  278.   CLRSCR;
  279.   WINDOW(C1,R1,C2+1,R2);
  280. {$ENDIF}
  281. END;
  282. (***************************************************************************)
  283. PROCEDURE CLEAR_LINE;
  284. { clears the current line }
  285. BEGIN
  286. {$IFDEF USEQWIK}
  287.   QFILL(R1+VROW-1,C1,1,WIDTH,BACKATTR,#32);
  288.   { FYI, the arguments for QFILL are:
  289.      QFILL(row,column,rows,columns,attribute,char);  }
  290. {$ELSE}
  291.   TEXTATTR:=BACKATTR;
  292.   WINDOW(C1,R1,C2,R2);
  293.   gotoxy(1,vrow); clreol;
  294.   WINDOW(C1,R1,C2+1,R2);
  295. {$ENDIF}
  296. END;
  297. (***************************************************************************)
  298. PROCEDURE BUMP_TXT(COUNT:LONGINT);
  299. { moves text at POSITION index over COUNT bytes, for inserting data }
  300. { this procedure does NOT change, position or cursor indexes }
  301. VAR I:LONGINT;
  302. BEGIN
  303.   inc(textsize,COUNT);
  304.   for i:=textsize downto position do { move everything forward 1 }
  305.     txt^[i]:=txt^[i-COUNT];
  306. END;
  307. (***************************************************************************)
  308. PROCEDURE DEL_CHARS(COUNT:LONGINT);
  309. { erase COUNT chars at position, shorten text array }
  310. var I:longint;
  311. BEGIN
  312.   FOR I:=POSITION TO (TEXTSIZE-1) DO
  313.     TXT^[I]:=TXT^[I+COUNT];
  314.   DEC(TEXTSIZE,COUNT);
  315. END;
  316.  
  317. (***************************************************************************)
  318. PROCEDURE GET_LINE_DATA(POS:LONGINT; VAR STARTINDEX,ENDINDEX,COL:LONGINT);
  319. { given the array index (position), calculate the start & ending index of the
  320.   current line, also returning VIRTUAL column position on the current line
  321.  
  322.   procedure returns:  1,1,1 if at the top of the file;
  323.   procedure returns:  textsize,textsize,1 at bottom of file
  324.  
  325.   This is one procedure, that if implemented in ASM would improve the
  326.   overall performance of this unit (I'm open to suggestions).
  327. }
  328. VAR i:longint;
  329. BEGIN
  330.   startindex:=0; endindex:=0; col:=0;
  331.   if pos<1 then exit;               { invalid position }
  332.   if pos>textsize then begin        { at end of text }
  333.     endindex:=textsize+1;
  334.   end else begin
  335.     for i:=pos to textsize do       { find end of line index }
  336.       if txt^[i]=CR then begin      { found CR at end of line }
  337.         endindex:=i;
  338.         i:=textsize;                { force end of loop }
  339.       end;
  340.     if endindex=0 then endindex:=textsize+1;  { last line obviously }
  341.   end;
  342.                                     { find beginning of line index }
  343.   for i:=(endindex-1) downto 1 do   { FOR checks=endvalue, if not increments! }
  344.     if txt^[i]=CR then begin        { found CR at beginning of line }
  345.       startindex:=i+1;              { index of previous CR+1 }
  346.       i:=1;                         { force end of loop }
  347.     end;
  348.   if startindex=0 then startindex:=1;  { begin of line is top of text }
  349.  
  350.   col:=pos-startindex+1;            { calculate VIRTUAL column position }
  351. END;
  352. (***************************************************************************)
  353. PROCEDURE STUFF_TXT(s:string);
  354. { add string/char to txt array, bump POSITION up one }
  355. VAR j,b1,e1,col1:longint; t:byte;
  356. BEGIN
  357.   t:=length(s);
  358.   if ((inserton) or (txt^[position]=CR)) and ((textsize+t)>textmax) then
  359. begin  { no more room }
  360.     write(#7); exit;
  361.   end;
  362.  
  363. { if xline, and text added, make sure to bump position to the end of line }
  364.   IF (XLINE) THEN BEGIN { pad the short line with spaces to the position }
  365.     GET_LINE_DATA(POSITION, b1,e1,col1);
  366.     j:=(offset+vcolumn)-(e1-b1+1);  { number of spaces to pad }
  367.     IF ((textsize+t+j)>textmax) then BEGIN { check for avail space }
  368.       write(#7); exit;
  369.     END;
  370.     bump_txt(j);
  371.     for b1:=position to (position+j-1) do
  372.       txt^[b1]:=SPACE;
  373.     XLINE:=FALSE;
  374.     POSITION:=POSITION+J;
  375.   END;
  376.  
  377.   if (inserton) OR (txt^[position]=CR) then
  378.     if (position<=textsize) then begin { insert }
  379.       bump_txt(t);
  380.       FOR J:=1 TO T DO BEGIN
  381.         txt^[position]:=ORD(S[J]);  { add/replace character }
  382.         INC(POSITION);              { move pointer up one }
  383.         INC(VCOLUMN);
  384.       END;
  385.       exit;
  386.     end else begin                  { append / position > textsize }
  387.       FOR J:=1 TO T DO BEGIN
  388.         inc(textsize);
  389.         txt^[textsize]:=ORD(S[J]);
  390.         INC(VCOLUMN);
  391.       END;
  392.       position:=textsize+1;         { position pointer at end of text }
  393.     end
  394.   else if position<=textsize then begin { overwrite }
  395.     FOR J:=1 TO T DO BEGIN
  396.       txt^[position]:=ORD(S[J]);        { overwrite current position }
  397.       inc(position);                    { move pointer one over }
  398.     END;
  399.     INC(VCOLUMN,T);
  400.   end else begin { append }
  401.     if ((textsize+T)>=textmax) then begin  { can't append if buffer full }
  402.       write(#7);
  403.       exit;
  404.     end;
  405.     FOR J:=1 TO T DO BEGIN
  406.       inc(textsize);
  407.       txt^[textsize]:=ORD(S[J]);
  408.     END;
  409.     position:=textsize+1;
  410.     INC(VCOLUMN,T);
  411.   end;
  412. END;
  413. (***************************************************************************)
  414. FUNCTION WINBOTTOM:LONGINT;
  415. { returns the text array index value of the last character in the text window }
  416. var i:longint; linecount:byte;
  417. BEGIN
  418.   LINECOUNT:=0;
  419.   FOR I:=WINTOP TO TEXTSIZE DO BEGIN
  420.     IF TXT^[I]=CR THEN INC(LINECOUNT);
  421.     IF LINECOUNT=HEIGHT THEN BEGIN { found last line in text window }
  422.       WINBOTTOM:=I;
  423.       EXIT;
  424.     END;
  425.   END; { for loop thru text }
  426.   WINBOTTOM:=TEXTSIZE; { end before last text line found, so text ends in
  427. window }
  428. END;
  429.  
  430. (***************************************************************************)
  431. PROCEDURE SHOW_LINE;
  432. { rewrites the current line to the window }
  433. VAR I,b1,e1,col1:longint; S:STRING;
  434. BEGIN
  435.   GET_LINE_DATA(position, b1,e1,col1);
  436.   IF (B1>TEXTSIZE) THEN BEGIN CLEAR_LINE; EXIT; END; { nothing there }
  437.   col1:=(offset+b1+width-1); if col1>textsize then col1:=textsize; {eol pos}
  438.   S:='';
  439.   for i:=(offset+b1) to col1 {(offset+b1+width-1)} do begin
  440.     if txt^[i]=CR then i:=col1 {(offset+b1+width-1)} { force end }
  441.     else begin
  442.       s:=s+chr(txt^[i]);
  443.     end;
  444.   end;
  445.   CLEAR_LINE;
  446. {$ifdef USEQWIK}
  447.   QWRITE(R1+VROW-1,C1,NORMATTR,S);
  448.   GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  449. {$ELSE}
  450.   TEXTATTR:=NORMATTR;
  451.   GOTOXY(1,VROW);  WRITE(S);
  452.   GOTOXY(VCOLUMN,VROW);
  453. {$ENDIF}
  454. END;
  455. (***************************************************************************)
  456. PROCEDURE SHOW_TXT;
  457. { display text to screen area
  458.   sets VROW and VCOLUMN to match displayed area where position
  459.   is and moves cursor to that location }
  460. var I,R,C,CWIDTH:LONGINT;
  461. BEGIN
  462.   R:=1; C:=1;  { set start row/column }
  463.   CWIDTH:=0;
  464.   CLEAR_WINDOW;
  465.  
  466.   { % hide cursor }
  467.   FOR I:=WINTOP TO TEXTSIZE DO BEGIN
  468.     IF (R>HEIGHT) OR (I>TEXTSIZE) THEN begin { check for outside vertical
  469. boundaries OR end }
  470.       {$IFDEF USEQWIK}
  471.         GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  472.       {$ELSE}
  473.         GOTOXY(VCOLUMN,VROW);
  474.       {$ENDIF}
  475.       EXIT;  { done, filled window }
  476.     END;
  477.     IF (TXT^[I]=CR) THEN BEGIN   { -------------- check for carriage return }
  478.       INC(R);   { bump row down }
  479.       CWIDTH:=0;
  480.       C:=1;
  481. { % IF TXT^[I+1]=10 THEN INC(I);  { check for additional LF / skip over }
  482.  
  483.     END ELSE BEGIN   { ----------------------------------- printable char }
  484.       INC(CWIDTH);
  485.       IF CWIDTH>OFFSET THEN       { if screen offset in effect }
  486.         IF C<= WIDTH THEN BEGIN    { if line not off the screen }
  487. {$IFDEF USEQWIK}
  488.           QWRITE(R1+R-1,C1+C-1,NORMATTR,CHR(TXT^[I]));
  489. {$ELSE}
  490.           GOTOXY(C,R); textattr:=normattr;
  491.           WRITE(CHR(TXT^[I]));
  492. {$ENDIF}
  493.           INC(C);
  494.         END else INC(C);  { increment column counter anyway even though not
  495. printed }
  496.      END;
  497.      IF I>TEXTSIZE THEN I:=TEXTSIZE;  { if bumped past, set to end loop }
  498.   END;  { FOR loop }
  499. {$IFDEF USEQWIK}
  500.   GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  501. {$ELSE}
  502.   GOTOXY(VCOLUMN,VROW);
  503. {$ENDIF}
  504.   EXIT;
  505. END;
  506. (***************************************************************************)
  507. PROCEDURE DISPLAY_TXT(VAR PT:POINTER);
  508. { display text, specified by pointer
  509.   can be used by an external viewing routine }
  510. VAR TEMP:POINTER;
  511. BEGIN
  512.   TEMP:=addr(TXT);
  513.   TXT:=PT;
  514.   SHOW_TXT;
  515.   TXT:=TEMP;
  516. END;
  517. (***************************************************************************)
  518. PROCEDURE SCROLLUP(LINES:BYTE);
  519. { scroll screen up x lines; does not change cursor or text pointer }
  520. var i,b1,e1,col1,LINECOUNT:longint;
  521. BEGIN
  522.   LINECOUNT:=0;
  523.   FOR I:=WINTOP DOWNTO 1 DO BEGIN
  524.     if txt^[i]=CR then begin  { found end of prev line }
  525.        INC(LINECOUNT);
  526.        IF (LINECOUNT=LINES) THEN BEGIN
  527.          GET_LINE_DATA(I, b1,e1,col1);
  528.          WINTOP:=B1;
  529.          EXIT;
  530.        END;
  531.     END; { cr found }
  532.   END; { for loop }
  533.   WINTOP:=1;
  534. END;
  535. (***************************************************************************)
  536. PROCEDURE SCROLLDOWN(LINES:BYTE);
  537. { scroll screen down x lines, does not change cursor or text pointer }
  538. var i,b1,e1,col1,LINECOUNT:longint;
  539. BEGIN
  540.   linecount:=0;
  541.   for i:=WINTOP to textsize do begin
  542.     if txt^[i]=CR then begin
  543.       { i=index pos of CR of next line }
  544.       inc(linecount);
  545.       if (linecount=lines) {or (i=textsize)} then begin
  546.         WINTOP:=i+1;
  547.         SHOW_TXT;
  548.         EXIT;
  549.       end;  { found specified number of lines }
  550.     end; { if CR found }
  551.   end; { loop thru text }
  552. END;
  553.  
  554. (***************************************************************************)
  555. PROCEDURE SET_POSITION;
  556. { sets POSITION index based on cursor location and WINTOP index }
  557. var I,b1,e1,col1,R,LINECOUNT:longint;
  558. BEGIN
  559.   R:=1; LINECOUNT:=1;
  560.   FOR I:=WINTOP TO TEXTSIZE DO BEGIN
  561.     if (VROW=R) then begin  { line cursor on found }
  562.       GET_LINE_DATA(I, b1,e1,col1);
  563.       IF ((E1-B1+1) < (VCOLUMN+OFFSET)) THEN BEGIN
  564.         POSITION:=E1;
  565.         XLINE:=TRUE;
  566.       END ELSE BEGIN
  567.         POSITION:=B1+VCOLUMN-1;
  568.         XLINE:=FALSE;
  569.       END;
  570.       EXIT;
  571.     end; { cursor line found }
  572.     if txt^[i]=CR then begin
  573.       INC(R);
  574.       INC(LINECOUNT);
  575.     end;
  576.   END; { for loop thru text }
  577.   POSITION:=TEXTSIZE+1;  { assuming cursor at end of text then }
  578.   VROW:=LINECOUNT;  { not sure if this should be here, but takes care
  579.                       of case where scrolling causes most of screen to
  580.                       be past the end of file (where the cursor pos is)
  581.                     }
  582.   GET_LINE_DATA(POSITION, b1,e1,col1);
  583.   IF (VCOLUMN>COL1) THEN XLINE:=TRUE ELSE BEGIN
  584.     POSITION:=B1+VCOLUMN+OFFSET-1;
  585.     XLINE:=FALSE;
  586.   END;
  587. END;
  588. (***************************************************************************)
  589. PROCEDURE SET_CURSOR;
  590. { finds position and sets VCOLUMN & VROW and OFFSET appropriately in window }
  591. { ALWAYS sets XLINE to FALSE }
  592. var i,b1,e1,col1,R,C:longint; screenchanged:BOOLEAN;
  593. BEGIN
  594.   R:=1; C:=1; SCREENCHANGED:=FALSE; XLINE:=FALSE;
  595.   FOR I:=WINTOP TO TEXTSIZE+1 DO BEGIN
  596.     IF I=POSITION THEN BEGIN   { found it ------------------------ }
  597.       if (c>offset) and (c<=(offset+width)) then begin  { in window }
  598.         dec(c,offset);
  599.       end else BEGIN
  600.         SCREENCHANGED:=TRUE;
  601.         IF (C<=WIDTH) THEN BEGIN
  602.           OFFSET:=0;
  603.         END ELSE BEGIN
  604.           OFFSET:=(C-WIDTH)+SCRBUMP;
  605.           C:=WIDTH-SCRBUMP;
  606.         END;
  607.       END;
  608.       VCOLUMN:=C;
  609.       VROW:=R;
  610.       IF (SCREENCHANGED) THEN SHOW_TXT else
  611. {$IFDEF USEQWIK}
  612.         GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  613. {$ELSE}
  614.         GOTOXY(VCOLUMN,VROW);
  615. {$ENDIF}
  616.       EXIT;
  617.     END; { position found }
  618.   IF TXT^[I]=CR THEN BEGIN
  619.     INC(R); C:=1;
  620.   END ELSE INC(C);
  621.   IF (R>HEIGHT) {OR (R<1)} THEN BEGIN
  622.     GET_LINE_DATA(WINTOP, b1,e1,col1);
  623.     WINTOP:=E1+1;
  624.     R:=HEIGHT;
  625.     SCREENCHANGED:=TRUE;
  626.   END;
  627.  END; { for }
  628. END;
  629. (***************************************************************************)
  630. PROCEDURE WORD_WRAP(startpoint,endpoint,length:LONGINT);
  631. { word wrap a section of text }
  632. var ccount,i,spacepos,lastcr:longint; showit:boolean;
  633. BEGIN
  634.   IF LENGTH=0 THEN EXIT;  { no length specified so get outta here }
  635.   SPACEPOS:=0; SHOWIT:=FALSE; CCOUNT:=0; LASTCR:=-1;
  636.   FOR I:=STARTPOINT TO (ENDPOINT-1) DO BEGIN
  637.     INC(CCOUNT);
  638.     IF TXT^[I]=SPACE THEN SPACEPOS:=I;
  639.     IF TXT^[I]=CR THEN    { end wrap when to CRs follow, otherwise -> space }
  640.       IF LASTCR=(I-1) THEN BEGIN
  641.         TXT^[I-1]:=CR; { restore prev CR }
  642.         SET_CURSOR;
  643.         SHOW_TXT;
  644.         EXIT;
  645.       END ELSE BEGIN
  646.         TXT^[I]:=SPACE;
  647.         SPACEPOS:=I;
  648.         LASTCR:=I;
  649.       END;
  650.     IF (CCOUNT)>LENGTH THEN BEGIN  { past point }
  651.       IF SPACEPOS=0 THEN BEGIN     { force a CR }
  652.         SPACEPOS:=POSITION; { save pos }
  653.         POSITION:=I;
  654.         BUMP_TXT(1);  { insert 1 byte at position }
  655.         INC(ENDPOINT);
  656.         POSITION:=SPACEPOS; { restore pos }
  657.         TXT^[I]:=CR;
  658.         CCOUNT:=0;
  659.       END ELSE BEGIN
  660.         TXT^[SPACEPOS]:=CR; { turn last space into a CR }
  661.         CCOUNT:=I-SPACEPOS; { calc next line len w/wrap }
  662.       END;
  663.       SHOWIT:=TRUE;
  664.     END; { line past length }
  665.   END; { for }
  666.   IF SHOWIT THEN BEGIN
  667.     SET_CURSOR;
  668.     SHOW_TXT;
  669.   END;
  670. END;
  671.  
  672. (***************************************************************************)
  673. FUNCTION LINEUP:LONGINT;
  674. { returns new index in file, one line up }
  675. { MOVES cursor on screen as well }
  676. var b1,b2,e1,e2, col1,col2,len1,len2:longint;
  677. BEGIN
  678.   GET_LINE_DATA(position, b1,e1,col1); { get data on current line }
  679.   len1:=e1-b1+1;                       { length of line + CR }
  680.   if b1=1 then BEGIN                   { check for top of text }
  681.     LINEUP:=POSITION; EXIT;
  682.   END;
  683.   GET_LINE_DATA(B1-1,     b2,e2,col2); { get data on previous line }
  684.   len2:=e2-b2+1;
  685.   IF (XLINE) THEN BEGIN
  686.     col2:=b2+vcolumn+offset-1; { in case of move to non-xline, set position }
  687.   END ELSE
  688.     col2:=b2+col1-1;  { index position of one line up, tentative }
  689.  
  690.   if col2<1 then col2:=1 else { top of file }
  691.     if (col2>e2) then begin   { previous line shorter than current line }
  692.       col2:=e2;               { make one line up, end of previous line }
  693.       XLINE:=TRUE;
  694.     end else begin
  695.       XLINE:=FALSE;
  696.     end;
  697.   LINEUP:=COL2;
  698.  
  699.   IF (WINTOP>col2) THEN BEGIN  { scroll the screen up }
  700.     WINTOP:=B2;
  701.     SHOW_TXT;
  702.   END ELSE DEC(VROW);  { bump cursor up }
  703. {$IFDEF USEQWIK}
  704.   GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  705. {$ELSE}
  706.   GOTOXY(VCOLUMN,VROW);
  707. {$ENDIF}
  708. END;
  709. (***************************************************************************)
  710. FUNCTION LINEDOWN:LONGINT;
  711. { returns new index in file, one line down }
  712. { MOVES cursor on screen as well }
  713. var b1,b2,e1,e2, col1,col2,len1,len2:longint;
  714. BEGIN
  715.   GET_LINE_DATA(position, b1,e1,col1); { get data on current line }
  716.   len1:=e1-b1+1;                       { calc length of line incl. CR }
  717.   if e1>=textsize then begin           { can't go down on last line }
  718.     LINEDOWN:=POSITION; EXIT;
  719.   end;
  720.   GET_LINE_DATA(e1+1,     b2,e2,col2); { get data on next line }
  721.   len2:=e2-b2+1;
  722.  
  723.   IF (XLINE) THEN BEGIN
  724.     col2:=b2+vcolumn+offset-1;   { in case of move to non-xline, set position }
  725.   END ELSE
  726.     col2:=b2+col1-1;   { index position of one line down, tentative }
  727.  
  728.   if (col2>e2) then begin  { next line position is past end of next line }
  729.       col2:=e2;            { make one line down, end of next line }
  730.       xline:=TRUE;
  731.     end else begin
  732.       xline:=FALSE;
  733.   end;
  734.   LINEDOWN:=COL2;
  735.  
  736.   IF (VROW=HEIGHT) THEN BEGIN   { down off screen, scroll text up }
  737.     SCROLLDOWN(1);  {WINTOP:=B2;}
  738.   END ELSE INC(VROW);  { bump screen down }
  739. {$IFDEF USEQWIK}
  740.   GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  741. {$ELSE}
  742.   GOTOXY(VCOLUMN,VROW);
  743. {$ENDIF}
  744. END;
  745. (***************************************************************************)
  746. PROCEDURE READ_TXT(VAR PT:POINTER;FILENAME:STRING;VAR TEXTSIZE:LONGINT);
  747. { reads text from file into buffer, strips LFs }
  748. { HORRIBLY SLOW, but not intended to be a real part of this unit }
  749. VAR
  750.     F    :FILE OF BYTE;
  751.     PTXT :^TXT_TYPE;
  752. BEGIN
  753.   PTXT:=PT;
  754.   ASSIGN(F,FILENAME);
  755.   RESET(F);
  756.   TEXTSIZE:=0;
  757.   IF IORESULT<>0 THEN EXIT;
  758.   IF EOF(F) THEN BEGIN CLOSE(F); EXIT; END;
  759.   WHILE NOT(EOF(F)) DO BEGIN
  760.     INC(TEXTSIZE);
  761.     READ(F,PTXT^[TEXTSIZE]);
  762.     if (Ptxt^[textsize]=10) then begin
  763.       dec(textsize);  { remove LFs }
  764.     end;
  765.     IF TEXTSIZE>=TEXTMAX THEN BEGIN
  766.       CLOSE(F);
  767.       EXIT;
  768.     END;
  769.   END;
  770.   CLOSE(F);
  771. END;
  772.  
  773. (***************************************************************************)
  774. PROCEDURE DIRECTION(C:BYTE);
  775. { act on direction keys }
  776. var b1,e1,col1:longint; T:BYTE;
  777. BEGIN
  778.       case C of
  779.        72:begin  { up }
  780.            POSITION:=LINEUP;
  781.          end;
  782.        80:begin  { down }
  783.             POSITION:=LINEDOWN;
  784.           end;
  785.        75:begin  { left }
  786.             if position=1 then begin
  787.               write(#7);
  788.               exit;
  789.             end;
  790.             if (xline) then begin
  791.               dec(vcolumn);
  792.               { check to see if moved onto text }
  793.               get_line_data(position,b1,e1,col1);
  794.               if (offset+vcolumn)=(e1-b1+1) then begin
  795.                 xline:=FALSE;
  796.               end;
  797.             end else begin  { not xline }
  798.               if txt^[position-1]=CR then begin      { back up one line? }
  799.                 get_line_data(position-1,b1,e1,col1);
  800.                 vcolumn:=col1;
  801.                 if col1>width then begin { left to prev line off screen }
  802.                   offset:=col1-width+2;
  803.                   vcolumn:=col1-offset;
  804.                   SHOW_TXT;
  805.                 end else offset:=0;
  806.                 dec(vrow)
  807.               end else begin
  808.                 dec(vcolumn);
  809.               end;
  810.               dec(position);
  811.             end; { xline }
  812.             if (vcolumn<1) and (offset>0) then begin
  813.               vcolumn:=1;
  814.               dec(offset);
  815.               SHOW_TXT;
  816.             end;
  817. {$IFDEF USEQWIK}
  818.             GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  819. {$ELSE}
  820.             GOTOXY(VCOLUMN,VROW);
  821. {$ENDIF}
  822.           end;
  823.        77:begin  { right }
  824.             if (xline) then begin
  825.               inc(vcolumn);
  826.             end else begin
  827.               inc(position);
  828.               inc(vcolumn);
  829.               if (txt^[position-1]=CR) OR ((position-1)>=TEXTSIZE) then begin
  830. { at eol }
  831.                 dec(position);
  832.                 xline:=true;
  833.               end;
  834.             end;
  835.  
  836.             IF (MAXCOLUMN>0) AND ((VCOLUMN+OFFSET)>MAXCOLUMN) THEN BEGIN
  837.               GET_LINE_DATA(POSITION,b1,e1,col1);
  838.               IF E1>=TEXTSIZE THEN BEGIN
  839.                 DEC(VCOLUMN);
  840.               END ELSE BEGIN
  841.                 POSITION:=E1+1;
  842.                 SET_CURSOR;
  843.                 EXIT;
  844.               END;
  845.             END;
  846.  
  847.             if vcolumn>width then begin { moved outside window }
  848.               inc(offset);
  849.               dec(vcolumn);
  850.               SHOW_TXT;
  851.             end;
  852. {$IFDEF USEQWIK}
  853.             GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  854. {$ELSE}
  855.             GOTOXY(VCOLUMN,VROW);
  856. {$ENDIF}
  857.           end;
  858.        71:begin  { HOME, to beginning of current line }
  859.             GET_LINE_DATA(POSITION,B1,E1,COL1);
  860.             POSITION:=B1; VCOLUMN:=1;
  861.             IF OFFSET>0 THEN BEGIN
  862.               OFFSET:=0;
  863.               SHOW_TXT;
  864.             END;
  865. {$IFDEF USEQWIK}
  866.             GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  867. {$ELSE}
  868.             GOTOXY(VCOLUMN,VROW);
  869. {$ENDIF}
  870.             XLINE:=FALSE;
  871.           end;
  872.        79:begin  { END, to end of current line }
  873.             GET_LINE_DATA(POSITION,B1,E1,COL1);
  874.             POSITION:=E1;
  875.             { calculate offset & cursor position }
  876.             IF (E1-(B1+OFFSET)+1)>WIDTH THEN BEGIN  { off screen }
  877.               offset:=(e1-b1+1)-width+2; {SCRBUMP}
  878.               vcolumn:=width-2; {SCRBUMP}
  879.               SHOW_TXT;
  880.             END ELSE VCOLUMN:=((E1-B1+1)-offset);
  881. {$IFDEF USEQWIK}
  882.             GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  883. {$ELSE}
  884.             GOTOXY(VCOLUMN,VROW);
  885. {$ENDIF}
  886.           end;
  887.        73:begin  { PGUP, up one screen }
  888.             IF (WINTOP=1) THEN BEGIN
  889.               POSITION:=1;
  890.               VCOLUMN:=1; VROW:=1;
  891. {$IFDEF USEQWIK}
  892.               GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  893. {$ELSE}
  894.               GOTOXY(VCOLUMN,VROW);
  895. {$ENDIF}
  896.             END ELSE BEGIN
  897.               SCROLLUP(HEIGHT);
  898.               SET_POSITION;
  899.               SHOW_TXT;
  900.             END;
  901.           end;
  902.        81:begin  { PGDN, down one screen }
  903.             IF (WINBOTTOM=TEXTSIZE) THEN BEGIN
  904.               POSITION:=TEXTSIZE+1;
  905.               SET_CURSOR;
  906.             END ELSE BEGIN
  907.               SCROLLDOWN(HEIGHT);
  908.               SET_POSITION;
  909.               SHOW_TXT;
  910.             END;
  911.           end;
  912.         82:BEGIN
  913.              INSERTON:=NOT(INSERTON);     { INS toggle insert status }
  914. { %      IF (INSERTON) THEN GETBLOCKCURSOR ELSE GETUNDERLINECURSOR;}
  915.            END;
  916.         83:BEGIN                        { DEL }
  917.              T:=ORD(TXT^[POSITION]);
  918.              IF POSITION=TEXTSIZE+1 THEN EXIT;
  919.              IF (XLINE) THEN BEGIN   { hitting DEL past eol, special case }
  920.                STUFF_TXT(#0);
  921.                DEC(POSITION);
  922.                DEC(VCOLUMN);
  923.                DEL_CHARS(1);
  924.              END;
  925.              DEL_CHARS(1);
  926.              IF (T=CR) OR (POSITION>=TEXTSIZE) THEN SHOW_TXT ELSE SHOW_LINE;
  927.            END;
  928.        132:begin  { CTRL-PgUP - top of text }
  929.              POSITION:=1; VROW:=1; VCOLUMN:=1; XLINE:=FALSE;
  930.              IF (WINTOP=1) AND (OFFSET=0) THEN
  931. {$IFDEF USEQWIK}
  932.                GOTORC(R1+VROW-1,C1+VCOLUMN-1)
  933. {$ELSE}
  934.                GOTOXY(VCOLUMN,VROW)
  935. {$ENDIF}
  936.              ELSE BEGIN
  937.                WINTOP:=1; OFFSET:=0;
  938.                SHOW_TXT;
  939.              END;
  940.           end;
  941.        115:begin  { CTRL <- }
  942.              if position<3 then exit;
  943.              for col1:=(position-2) downto 1 do
  944.                if (txt^[col1]=SPACE) then begin
  945.                  position:=col1+1;
  946.                  if position<wintop then begin
  947.                    wintop:=1;
  948.  { this could be avoided if set-cursor started at 1 instead of wintop,
  949.    but it would reduce overal performance }
  950.                    set_cursor;
  951.                    show_txt
  952.                  end else
  953.                    set_cursor;
  954.                  exit;
  955.                end;
  956.            end;
  957.        116:begin  { CTRL -> }
  958.              if position>=textsize then exit;
  959.              for col1:=position+1 to textsize do
  960.                if (txt^[col1]=SPACE) then begin
  961.                  position:=col1+1;
  962.                  set_cursor;
  963.                  exit;
  964.                end;
  965.            end;
  966.        118:begin  { CTRL-PgDN - end of text }
  967.              position:=textsize+1;
  968.              SET_CURSOR;
  969.          end;
  970.        67:BEGIN    { F9 }
  971.           END;
  972.       end; { case }
  973. end;
  974.  
  975. (***************************************************************************)
  976. FUNCTION PARSE_INPUT:BYTE;
  977. { main encapsulation of editing routine, read keys and act }
  978. var c         :byte;
  979.     fkey      :boolean;
  980.     leaving   :boolean;
  981.     b1,e1,col1:longint;
  982. { RETURNS:
  983.       1=ESC
  984.       2=ALT-X
  985.       3=F1
  986.       4=F10
  987.       5=F2
  988. }
  989. BEGIN
  990.   LEAVING:=FALSE;
  991.   REPEAT
  992.     c:=getinput(fkey);
  993.  
  994.     IF (C=27) OR ((FKEY) AND (C IN [59,45,60,68])) THEN BEGIN  { exit
  995. conditions }
  996.       IF C=27 THEN PARSE_INPUT:=1 ELSE  { esc }
  997.       IF C=45 THEN PARSE_INPUT:=2 ELSE  { Alt-X }
  998.       IF C=59 THEN PARSE_INPUT:=3 ELSE  { F1 }
  999.       IF C=68 THEN PARSE_INPUT:=4 ELSE  { F10 }
  1000.       IF C=60 THEN PARSE_INPUT:=5;      { F2 }
  1001.       EXIT;
  1002.     END ELSE
  1003.     IF (FKEY) THEN BEGIN  { ------------------ eval FNC & CURSOR keys ----- }
  1004.       DIRECTION(C);
  1005.     END { if function key pressed }
  1006.     ELSE BEGIN                      { alphanumeric key - process data }
  1007.       CASE C OF                     { check alpha keys }
  1008.        REFORMAT:BEGIN               { CTRL-B, 02, REFORMAT }
  1009.             GET_LINE_DATA(POSITION,b1,e1,col1);
  1010.             WORD_WRAP(B1,TEXTSIZE,MAXCOLUMN);
  1011.           END;
  1012.        CR:begin                     { carriage return }
  1013.             IF (INSERTON) OR (POSITION>TEXTSIZE) THEN BEGIN
  1014.               OFFSET:=0;
  1015.               INC(VROW);
  1016.               IF VROW>HEIGHT THEN BEGIN
  1017.                  SCROLLDOWN(1);
  1018.                  DEC(VROW);
  1019.                END;
  1020.                STUFF_TXT(CHR(C));
  1021.                VCOLUMN:=1;
  1022.                SHOW_TXT;
  1023.              end ELSE BEGIN  { enter pressed with overwrite on }
  1024.                GET_LINE_DATA(POSITION,B1,E1,COL1);
  1025.                POSITION:=E1+1;
  1026.                OFFSET:=0;
  1027.                SET_CURSOR;
  1028.                show_txt;
  1029.              END;
  1030.            END;
  1031.         08:IF POSITION<>1 THEN BEGIN    { backspace }
  1032.              IF (XLINE) THEN BEGIN   { can't erase dead zone }
  1033.                 DEC(VCOLUMN);        { just move cursor left }
  1034.                 SET_POSITION;
  1035.              END ELSE BEGIN
  1036.                DEC(POSITION);
  1037.                IF TXT^[POSITION]=CR THEN BEGIN { backspace/erase line }
  1038.                  DEL_CHARS(1);
  1039.                  SET_CURSOR;
  1040.                  SHOW_TXT;
  1041.                END ELSE BEGIN
  1042.                  DEL_CHARS(1);
  1043.                  DEC(VCOLUMN);
  1044.                  IF (VCOLUMN=0) THEN
  1045.                    IF (OFFSET>=SCRBUMP) THEN BEGIN
  1046.                      DEC(OFFSET,SCRBUMP); VCOLUMN:=SCRBUMP;
  1047.                      SHOW_TXT;
  1048.                    END ELSE BEGIN
  1049.                      OFFSET:=0; SET_CURSOR;
  1050.                      SHOW_TXT;
  1051.                    END
  1052.                  ELSE SHOW_LINE;
  1053.                END;
  1054.              END; { xline / else }
  1055. {$IFDEF USEQWIK}
  1056.              GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  1057. {$ELSE}
  1058.              GOTOXY(VCOLUMN,VROW);
  1059. {$ENDIF}
  1060.            END;
  1061.          09:BEGIN                      { TAB }
  1062.               GET_LINE_DATA(POSITION, b1,e1,col1);
  1063.               col1:=tabsize-((position-b1) mod tabsize); { spaces to next tab
  1064. stop }
  1065.               IF (INSERTON) THEN BEGIN
  1066.                 stuff_txt(SPACES(COL1));
  1067.                 SHOW_LINE;
  1068.               END ELSE BEGIN
  1069.                 INC(VCOLUMN,COL1);
  1070.                 IF VCOLUMN>WIDTH THEN BEGIN
  1071.                   INC(OFFSET,SCRBUMP);
  1072.                   DEC(VCOLUMN,SCRBUMP);
  1073.                   SHOW_TXT;
  1074.                 END;
  1075.                 IF (POSITION+COL1)>E1 THEN BEGIN
  1076.                   POSITION:=E1; XLINE:=TRUE;
  1077.                 END ELSE begin POSITION:=POSITION+COL1; XLINE:=FALSE; END;
  1078. {$IFDEF USEQWIK}
  1079.                 GOTORC(R1+VROW-1,C1+VCOLUMN-1);
  1080. {$ELSE}
  1081.                 GOTOXY(VCOLUMN,VROW);
  1082. {$ENDIF}
  1083.               END;
  1084.             END;
  1085.          25:BEGIN                      { CTRL-Y / ERASE LINE }
  1086.               GET_LINE_DATA(POSITION, b1,e1,col1);
  1087.               IF E1>TEXTSIZE THEN E1:=E1-B1 ELSE E1:=E1-B1+1;
  1088.               POSITION:=B1; { E1:=E1-B1+1; }
  1089.               OFFSET:=0; VCOLUMN:=1;
  1090.               DEL_CHARS(E1);
  1091.               SHOW_TXT;
  1092.               IF POSITION>TEXTSIZE THEN POSITION:=TEXTSIZE+1;
  1093.             END;
  1094.         ELSE BEGIN   {------------------ unspecific alphanumeric char }
  1095.           STUFF_TXT(CHR(C));           { store it }
  1096.           IF MAXCOLUMN=0 THEN BEGIN    { check for column boundaries }
  1097.             IF VCOLUMN>WIDTH THEN BEGIN
  1098.               INC(OFFSET,SCRBUMP);
  1099.               DEC(VCOLUMN,SCRBUMP);
  1100.               SHOW_TXT;
  1101.             END;
  1102.           END ELSE BEGIN  { limited screen/line size }
  1103.             SHOW_LINE;
  1104.             IF ((VCOLUMN+OFFSET)>MAXCOLUMN+1) THEN BEGIN  { hit edge limit }
  1105.               get_line_data(position,b1,e1,col1);
  1106.               word_wrap(b1,textsize,MAXCOLUMN);
  1107.             END ELSE BEGIN
  1108.               IF VCOLUMN>WIDTH THEN BEGIN { maxcolumn>width but set }
  1109.                 INC(OFFSET,SCRBUMP);
  1110.                 DEC(VCOLUMN,SCRBUMP);
  1111.                 SHOW_TXT;
  1112.               END;
  1113.             END;
  1114.           END;
  1115.           SHOW_LINE;
  1116.         END;
  1117.       END; { case }
  1118.     END { alpha key }
  1119.   UNTIL LEAVING;
  1120. END;
  1121.  
  1122. (***************************************************************************)
  1123. PROCEDURE SETUP_TEXT_SETTINGS(Row1,Column1,Row2,Column2:BYTE;DRAWBOX:BOOLEAN);
  1124. { sets appropriate system values for text window }
  1125. BEGIN
  1126.   R1:=ROW1; C1:=COLUMN1; R2:=ROW2; C2:=COLUMN2;  { set global position of win }
  1127. { % these are arbitrary attribute values - tweak them to suit your tastes }
  1128.   NORMATTR:=37; { % }
  1129.   BACKATTR:=37; { % }
  1130.   BORDATTR:=36; { % }
  1131.   OFFSET:=0;
  1132.   INSERTON:=TRUE;
  1133.   XLINE:=FALSE;
  1134.   HEIGHT:=R2-R1+1;  { current height of text window }
  1135.   WIDTH:=C2-C1+1;   { current width (in columns) of text window }
  1136.   SCRBUMP:=WIDTH DIV 2;
  1137.   VROW:=1;          { virtual row and column of cursor inside text window }
  1138.   VCOLUMN:=1;
  1139.  
  1140. { % maxcolumn sets automatic formatting and word wrapping !! }
  1141. {  MAXCOLUMN:=WIDTH; { set to 0 to disable word wrap and line length limits }
  1142.   MAXCOLUMN:=0;   { no word wrapping }
  1143.  
  1144.   position:=1;
  1145.   wintop:=1;
  1146.   IF DRAWBOX THEN BEGIN
  1147.     DRAW_BOX(R1,C1,R2,C2);
  1148.     { DRAW_BOX must be prior to initialize window if not using qwik }
  1149.     INITIALIZE_WINDOW(R1,C1,R2,C2);
  1150.   END;
  1151. END;
  1152. (***************************************************************************)
  1153. PROCEDURE EDIT(PT:POINTER;VAR RETURNCODE:BYTE);
  1154. { Edit text; assumes text has already been initialized }
  1155. BEGIN
  1156.   TXT:=PT;    { assign specified text pointer to working name }
  1157.   SHOW_TXT;
  1158.  
  1159.   RETURNCODE:=PARSE_INPUT;
  1160. { RETURNCODE the following values based on keys pressed:
  1161.       1=ESC
  1162.       2=ALT-X
  1163.       3=F1
  1164.       4=F10
  1165.       5=F2
  1166. }
  1167. END;
  1168. (***************************************************************************)
  1169. END. { Unit MPEDITOR.PAS }
  1170.